#! /usr/bin/python
#
# webkit-update  - WebKit nightly build updater for Mac OS X.
# Copyright (c) 2008 Taylor Malloy
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import urllib, re, os
from downloader import *
from webkit_site_parser import *
from appscript import *
from plistlib import *

url = "http://nightly.webkit.org"
version_name = "Mac OS X"
save_location = "/Users/tmalloy/Desktop/"
volume_name = "Webkit"
app_name = "WebKit"
plist_file = "webkit_downloader.plist"
current_version = ""

def mount_webkit(file_location):
    cmd = "hdid -plist " + file_location
    result = os.popen(cmd)
    vol_name = get_volumename(result)
    print "Mounting volume as " + vol_name + "..."
    global volume_name
    volume_name = vol_name

def get_volumename(plist):
    plist = Plist.fromFile(plist)
    for list in plist["system-entities"]:
        if list.has_key("mount-point"):
            location = list["mount-point"]
            break

    p = re.compile('[a-zA-Z0-9 ]+$')
    name = p.search(location).group()
    return name

def unmount_webkit():
    cmd = "df"
    result = os.popen(cmd)
    
    string_result = result.read()
    lines = string_result.split("\n")
    
    for line in lines:
        if volume_name in line:
            p = re.compile('/dev/\w+')
            disk_device = p.search(line).group()
            print "Unmounting " + disk_device + "..."
            cmd = "hdiutil detach " + disk_device
            os.popen(cmd)


def copy_new_version():
    isrunning = app('System Events').processes[its.name == app_name].exists()
    if isrunning:
        webkit = app("WebKit")
        print "Trying to quit WebKit, please accept if asked..."
        try:
            webkit.quit()
        except CommandError:
            print "User canceled webkit exit, exiting..."
            sys.exit(1)

    print "Copying new version over..."
    p = re.compile(volume_name + "/$")
    finder = app("Finder")
    disk = finder.computer_container
    for i in range(1, len(disk.folders()) + 1): # for each folder
        if disk.folders[i].displayed_name() == u"WebKit": # if the volume's displayed name is webkit (location could still be "/Volumes/Webkit 1")
            file_url_encoded = disk.folders[i].URL() # ex: "/Volumes/WebKit%201"
            file_url = urllib.unquote(file_url_encoded) # get its absolute location (different than its name and folder) # to: "/Volumes/Webkit 1"
            if bool(p.search(file_url)) == True: # if volume name matches volume location determined from mounting process
                disk.folders[i].items[app_name].duplicate(to=finder.startup_disk.folders["Applications"], replacing=True) # copy new version to applications, replacing old version

def remove_volume(file_location):
    cmd = "rm " + file_location
    print "Removing downloaded volume..."
    os.popen(cmd)

def get_version(file_string):
    """Returns the version found in the string passed to it. Looks for a
    number between a "/" and ".dmg". The ".dmg" must also end the string"""
    p = re.compile("/[^0-9/]*(?P<version>[0-9]+)[^/]*\.dmg$")
    
    if not p.search(file_string): # if version number is in name
        print "Could not find version number, version will not be saved..."
        return

    webkit_version = p.search(file_string).group('version')
    return webkit_version
    #global current_version = webkit_version

def write_version():
    plist = Plist(
        version = current_version
        )

    plist.write(plist_file)

def update_version(file_location):
    global current_version
    current_version = get_version(file_location)

def newer_version(to_download):
    return get_version(to_download) > current_version

def read_plist():
    plist = Plist.fromFile(plist_file)
    global current_version
    try:
        current_version = plist["version"]
    except:
        pass

def main():
    
    try:
        read_plist()
    except IOError:
        pass

    # open and download url html
    print "Checking for " + version_name + " from: " + url
    f = urllib.urlopen(url)
    s = f.read()
    
    # Try and process the page.
    parser = Webkit_Parser(version_name)
    parser.parse(s)
    
    # Get the hyperlinks.
    extension = parser.get_hyperlinks()

    # Check if the currently downloaded version is the newest

    if current_version != "":
        if not newer_version(extension):
            print "Already have newest version, exiting..."
            sys.exit(0)

    print "Download url is: " + url + extension

    # Extract file name from extension ex: /files/trunk/mac/Webkit-SVN-R32945.dmg
    p = re.compile('[a-zA-Z0-9-\.]+$')
    name = p.search(extension).group()

    file_location = save_location + name # absolute file location derived from save folder and file name

    print "Saving to: " + file_location
    
    # download the file
    downloader = Downloader()
    downloader.download(url + extension, file_location)

    # mount the dmg file
    mount_webkit(file_location)

    # Copy new version to Applications folder, overwriting old version
    copy_new_version()
    update_version(file_location)
    write_version()
    
    # Unmount dmg file
    unmount_webkit()
    
    # Remove downloaded dmg file
    remove_volume(file_location)

    print "Done."

if __name__ == "__main__":
    main()
